package cn.tedu.st.security.service.Impl;

import cn.tedu.st.security.pojo.dto.UserDTO;
import cn.tedu.st.security.pojo.vo.UserDetailsImpl;
import cn.tedu.st.security.service.UserService;
import cn.tedu.st.base.util.JwtUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private AuthenticationManager authenticationManager;
    //redis序列化的工具
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public HashMap<String, Object> login(UserDTO userDTO) {
        log.debug("进入UserServiceImpl--------------");
        // 创建一个包含用户名和密码的认证令牌（UsernamePasswordAuthenticationToken），
        // 用于传递给Spring Security进行身份验证。
        // 创建认证令牌
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userDTO.getUsername(), userDTO.getPassword());
        log.debug("创建认证令牌：{}", authenticationToken);
        // 执行认证
        log.debug("开始执行认证------");
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        log.debug("执行认证结束------：{}，把用户信息封装到authenticate", authenticate);
        // 使用AuthenticationManager对提供的认证令牌进行身份验证。
        // 如果认证成功，返回一个包含用户信息的Authentication对象；
        // 如果认证失败，则抛出异常。


        // 检查认证结果是否为null。如果认证结果为null，表示登录失败。
        // 这里使用Objects.isNull()方法来判断authenticate对象是否为空。
        log.debug("检查认证结果authenticate是否为null：{}", Objects.isNull(authenticate));
        if (Objects.isNull(authenticate)) {
            // 抛出自定义的RuntimeException，提示登录失败。
            log.debug("抛出自定义的RuntimeException，提示登录失败");
            throw new RuntimeException("登录失败");
        }

        //从authenticate拿到用户信息
        UserDetailsImpl userDetailsIMpl = (UserDetailsImpl)authenticate.getPrincipal();
        log.debug("从authenticate.getPrincipal()拿到用户信息：{}", userDetailsIMpl);
        //将用户信息转为json字符串
        String jsonString = JSON.toJSONString(userDetailsIMpl);
        log.debug("将用户信息转为json字符串jsonString：{}", jsonString);
        //生成jwt
        log.debug("通过JwtUtil.createJWT（jsonString）开始生成jwt");
        String jwt = JwtUtil.createJWT(jsonString, null);


        //jwt的键名
        String tokenKey="token_"+jwt;
        //存储redis白名单
        redisTemplate.opsForValue().set(tokenKey,jwt,JwtUtil.JWT_TTL/1000, TimeUnit.SECONDS);


        log.debug("生成结束--jwt：{}", jwt);
        //存储redis
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", jwt);
        map.put("username",userDetailsIMpl.getUsername());
        log.debug("UserServiceImpl结束--------返回的map={}", map);
        return map;
    }
}
